<template>
  <div id="app">
    <div class="socket-tip" v-show="status == 3">
      <i class="el-icon-error"></i>
      <span class="socket-tip-text">与服务器连接已断开</span>
      <el-button
        class="socket-tip-button"
        size="mini"
        type="danger"
        plain
        @click="connect">
        重新连接
      </el-button>
    </div>
    <create
      ref="create"
      :queue="queue"
      @create="create"/>
    <quests
      :queue="queue"
      @command="command"
      @log="viewLog"
      @load="loadConfig"
      @show="showResult"/>
    <result ref="result" :queue="queue"/>
    <log ref="log" :logs="logs" :queue="queue"/>
  </div>
</template>

<script>
import Create from './components/Create'
import Quests from './components/Quests'
import Result from './components/Result'
import Log from './components/Log'

export default {
  components: {
    Create,
    Quests,
    Result,
    Log
  },
  data() {
    return {
      socket: null,
      status: 0, // 0:初始未连接 1:连接中 2:已连接 3:已断开
      queue: [],
      logs: {}
    }
  },
  methods: {
    connect() {
      if (this.socket) {
        return
      }
      const socket = new WebSocket(`${location.protocol == 'https:' ? 'wss' : 'ws'}://${location.host}/ws`)
      socket.onopen = () => {
        this.status = 2
      }
      socket.onmessage = e => {
        const obj = JSON.parse(e.data)
        switch (obj.type) {
          case 'config':
            this.$refs.create.loadTemplate(obj)
            break
          case 'list':
            this.queue = obj.quests
            break
          case 'create':
            this.queue.push(obj.quest)
            this.$message(`任务 #${obj.quest.id} 已创建`)
            break
          case 'start': {
            const index = this.queue.findIndex(q => q.id == obj.id)
            if (index < 0) {
              break
            }
            const quest = this.queue[index]
            quest.status = 2
            this.queue.splice(index, 1)
            this.queue.splice(0, 0, quest)
            this.$set(this.logs, quest.id, '')
            this.$refs.log.changeSelected(quest.id)
            this.$message(`任务 #${quest.id} 已开始`)
            break
          }
          case 'queue': {
            let index = this.queue.findIndex(q => q.id == obj.id)
            if (index < 0) {
              break
            }
            const quest = this.queue[index]
            quest.status = 1
            this.queue.splice(index, 1)
            index = this.queue.findIndex(q => q.status != 1 && q.status != 2)
            if (index < 0) {
              this.queue.push(quest)
            } else {
              this.queue.splice(index, 0, quest)
            }
            break
          }
          case 'cancel': {
            let index = this.queue.findIndex(q => q.id == obj.id)
            if (index < 0) {
              break
            }
            const quest = this.queue[index]
            quest.status = 0
            this.queue.splice(index, 1)
            this.queue.push(quest)
            break
          }
          case 'delete': {
            let index = this.queue.findIndex(q => q.id == obj.id)
            if (index < 0) {
              break
            }
            this.queue.splice(index, 1)
            this.$delete(this.logs, obj.id)
            this.$refs.create.deleteQuest(obj.id)
            this.$message(`任务 #${obj.id} 已删除`)
            break
          }
          case 'stop': {
            let index = this.queue.findIndex(q => q.id == obj.id)
            if (index < 0) {
              break
            }
            const quest = this.queue[index]
            quest.status = 3
            quest.result = obj.result
            this.queue.splice(index, 1)
            this.queue.push(quest)
            this.$refs.result.changeSelected(quest.id)
            this.$message.success(`任务 #${quest.id} 已完成`)
            break
          }
          case 'error': {
            let index = this.queue.findIndex(q => q.id == obj.id)
            if (index < 0) {
              break
            }
            const quest = this.queue[index]
            quest.status = 4
            quest.error = obj.error
            this.queue.splice(index, 1)
            this.queue.push(quest)
            this.$message.error(`任务 #${quest.id} 失败`)
            break
          }
          case 'log':
            if (this.logs[obj.id] == null) {
              this.$set(this.logs, obj.id, obj.message)
            } else {
              this.logs[obj.id] += obj.message
            }
            break
          default:
            console.log(obj)
            break
        }
      }
      socket.onclose = () => {
        this.socket = null
        this.status = 3
      }
      this.socket = socket
      this.status = 1
      window.socket = socket
    },
    create(obj) {
      if (this.status != 2) {
        return
      }
      this.socket.send(JSON.stringify({ command: 'create', quest: obj }))
    },
    command(obj) {
      if (this.status != 2) {
        return
      }
      this.socket.send(JSON.stringify(obj))
    },
    viewLog(id) {
      if (this.logs[id] == null) {
        this.$message(`任务 #${id} 暂无日志输出`)
      } else {
        this.$refs.log.changeSelected(id)
        this.$refs.log.$el.scrollIntoView({ behavior: 'smooth' })
      }
    },
    loadConfig(id) {
      const quest = this.queue.find(q => q.id == id)
      if (quest) {
        this.$refs.create.loadConfig(quest)
        this.$refs.create.$el.scrollIntoView({ behavior: 'smooth' })
      }
    },
    showResult(id) {
      this.$refs.result.changeSelected(id)
      this.$refs.result.$el.scrollIntoView({ behavior: 'smooth' })
    }
  },
  mounted() {
    this.connect()
  }
}
</script>

<style>
.title {
  font-weight: bold;
}

.el-input,
.el-select {
  width: 200px;
}

.select-prefix {
  margin-left: 15px;
  height: 100%;
  display: flex;
  align-items: center;
  color: black;
}

.el-input-number .el-input__inner {
  text-align: left;
}

.socket-tip {
  margin-bottom: 10px;
  padding: 5px 20px;
  border-radius: 4px;
  background-color: #fef0f0;
  color: #f56c6c;
}

.socket-tip-text,
.socket-tip-button {
  margin-left: 20px;
}

.quests,
.log {
  margin-top: 10px;
}
</style>
